package main

/*
需要安装3方分词库
go get -u github.com/huichen/sego
*/
import (
	"fmt"
	"github.com/huichen/sego"
	"regexp"
	"strings"
)

type StringInfo struct {
	info        string
	len         int
	punctuation bool
	lang        int //0:中文，1：英文
}

//设置阈值，日文百分比
var japanProportion float32 = 0.4

//设置阈值，最长字符长度
var maxlen int = 100

var strtt string = "高校１年時よりネット上での翻訳活動を始め、以来、パブリックドメインになった文芸の各種翻訳を共有作品として提供しつづけている。現在は翻訳研究を進めるとともに、フリーランスの翻訳家・執筆家としても活躍中。"

var str0 string = " 生活对我们任何人来说都不容易！我们必须努力，最重要的是我们必须相信自己。我们必须相信，我们每个人都能够做得很好，而且，当我们发现这是什么时，我们必须努力工作，直到我们成功。"

//混合语言
var str1 string = "标准语音:使用统计参数合成和/或串联合成技术创建标准的语音。 这些语音是高度可识别，听起来很自然。 您可以轻松实现在多个 45 语言中，与范围广泛的语音选项说出您的应用程序。 这些语音提供高发音的准确性，包括对缩写、 首字母缩略词扩展、 日期/时间的解释、 polyphones，和的详细信息的支持。 使用标准的语音用户与你的内容时传递语音交互，从而提高应用程序和服务可访问性。"

//标准英文
var str2 string = "The manufacturing industry is regarded as the foundation of Dongguan, and has made sure the city is well known around the world. Focusing on the development of sci-tech innovation and manufacturing industry, Dongguan will make an effort to participate in the construction of Guangdong-Hong Kong-Macao Greater Bay Area (GBA) by taking advantage of its current industrial and technological bases."

//过长中文
var str3 string = "生活对我们任何人来说都不容易,我们必须努力，最重要的是我们必须相信自己,我们必须相信，我们每个人都能够做得很好，而且，当我们发现这是什么时，我们必须努力工作，直到我们成功,生活对我们任何人来说都不容易,我们必须努力，最重要的是我们必须相信自己,我们必须相信，我们每个人都能够做得很好，而且，当我们发现这是什么时，我们必须努力工作，直到我们成功,生活对我们任何人来说都不容易,我们必须努力，最重要的是我们必须相信自己,我们必须相信，我们每个人都能够做得很好，而且，当我们发现这是什么时，我们必须努力工作，直到我们成功,生活对我们任何人来说都不容易,我们必须努力，最重要的是我们必须相信自己,我们必须相信，我们每个人都能够做得很好，而且，当我们发现这是什么时，我们必须努力工作，直到我们成功。"

//无符号中文
var str4 string = "生活对我们任何人来说都不容易我们必须努力最重要的是我们必须相信自己我们必须相信我们每个人都能够做得很好而且当我们发现这是什么时生活对我们任何人来说都不容易我们必须努力最重要的是我们必须相信自己我们必须相信我们每个人都能够做得很好而且当我们发现这是什么时生活对我们任何人来说都不容易我们必须努力最重要的是我们必须相信自己我们必须相信我们每个人都能够做得很好而且当我们发现这是什么时生活对我们任何人来说都不容易我们必须努力最重要的是我们必须相信自己我们必须相信我们每个人都能够做得很好而且当我们发现这是什么时"

//过长英文
var str5 string = "The manufacturing industry is regarded as the foundation of Dongguan, and has made sure the city is well known around the world,The manufacturing industry is regarded as the foundation of Dongguan, and has made sure the city is well known around the world,The manufacturing industry is regarded as the foundation of Dongguan, and has made sure the city is well known around the world,The manufacturing industry is regarded as the foundation of Dongguan, and has made sure the city is well known around the world,The manufacturing industry is regarded as the foundation of Dongguan, and has made sure the city is well known around the world,The manufacturing industry is regarded as the foundation of Dongguan, and has made sure the city is well known around the world."

//无符号英文
var str6 string = "The manufacturing industry is regarded as the foundation of Dongguan and has made sure the city is well known around the world The manufacturing industry is regarded as the foundation of Dongguan and has made sure the city is well known around the world The manufacturing industry is regarded as the foundation of Dongguan and has made sure the city is well known around the world The manufacturing industry is regarded as the foundation of Dongguan and has made sure the city is well known around the world The manufacturing industry is regarded as the foundation of Dongguan and has made sure the city is well known around the world The manufacturing industry is regarded as the foundation of Dongguan and has made sure the city is well known around the world The manufacturing industry is regarded as the foundation of Dongguan and has made sure the city is well known around the world "

//
var str7 string = "标准语音:使用统计参数合成和/或串联合成技术创建标准的语音。这些语音是高度可识别，听起来很自然。 您可以轻松实现在多个 45 语言中，与范围广泛的语音选项说出您的应用程序。 这些语音提供高发音的准确性，包括对缩写、 首字母缩略词扩展、 日期/时间的解释和的详细信息的支持。 使用标准的语音用户与你的内容时传递语音交互，从而提高应用程序和服务可访问性。"

//
var str8 string = "The manufacturing industry 14 is regarded as the foundation of Dongguan, and has made sure the city is well known around the world. Focusing on the development of sci-tech innovation and manufacturing industry, Dongguan will make an effort to participate in the construction of Guangdong-Hong Kong-Macao Greater Bay Area (GBA) by taking advantage of its current industrial and technological bases."

func main() {
	var segmenter sego.Segmenter
	segmenter.LoadDictionary("D:/GOPATH/src/github.com/huichen/sego/data/dictionary.txt")
	if filterFun(strtt) {
		var sinfo StringInfo = stringPackage(strtt)
		fmt.Println(sinfo.lang)
		var resList []string
		var resListNew []string
		//基本分句
		if sinfo.lang != 2 {
			firstList := firstSlice(sinfo.info)
			infoList := listPackage(firstList)
			for _, val := range infoList {
				if val.len > maxlen {
					if val.punctuation {
						centList := secondSlice(val.info)
						for _, v := range centList {
							resList = append(resList, v)
						}
					} else {
						resList = append(resList, val.info)
					}
				} else {
					resList = append(resList, val.info)
				}
			}
			resList = removeNUllStr(resList)
			resListPa := listPackage(resList)
			for _, val := range resListPa {
				if val.len > maxlen {
					centList := thirdSlice(val.info, segmenter)
					for _, v := range centList {
						resListNew = append(resListNew, v)
					}
				} else {
					resListNew = append(resListNew, val.info)
				}
			}
		} else {
			fmt.Println("格式存在问题")
		}
		resListNew = removeNUllStr(resListNew)
		for _, v := range resListNew {
			fmt.Println(v + ".")
		}
	} else {
		fmt.Println("格式存在问题")
	}
}

//第二层逗号切分
func secondSlice(str string) (list []string) {
	list1 := strings.FieldsFunc(str, split1)
	listPa := listPackage(list1)
	var lon int = 0
	var temp string = ""
	//var sign bool = false
	for _, v := range listPa {
		if lon+v.len <= maxlen {
			if temp != "" {
				temp = temp + "," + v.info
			} else {
				temp = v.info
			}
			lon = lon + v.len
			//sign = true
		} else {
			list = append(list, temp)
			temp = v.info
			lon = v.len
			//sign = false
		}
	}
	//if sign {
	list = append(list, temp)
	//}
	return
}

//第三层强制切分
func thirdSlice(str string, segmenter sego.Segmenter) (list []string) {
	wordList := sliceWord(str, segmenter)
	var lon int = 0
	var temp string = ""
	//var sign bool = false
	for _, v := range wordList {
		if lon+len(v) <= maxlen {
			temp = temp + v
			lon = lon + len(v)
			//sign = true
		} else {
			list = append(list, temp)
			temp = v
			lon = len(v)
			//sign = false
		}
	}
	//if sign {
	list = append(list, temp)
	//}
	return
}

//第一层一般切分
func firstSlice(str string) (list []string) {
	list = strings.FieldsFunc(str, split)
	return
}

//list封装打包
func listPackage(strlist []string) []StringInfo {
	var res []StringInfo
	for _, val := range strlist {
		res = append(res, stringPackage(val))
	}
	return res
}

//封装打包
func stringPackage(str string) (info StringInfo) {
	var sinfo StringInfo
	sinfo.info = str
	sinfo.len = len(str)
	sinfo.lang = langJudge(str)
	sinfo.punctuation = punctuationSign(str)
	return sinfo
}

//判定是否有标点
func punctuationSign(str string) (sign bool) {
	reg := regexp.MustCompile(`[\pP]+`)
	//fmt.Printf("%q\n", reg.FindAllString(str, -1))
	len1 := len(reg.FindAllString(str, -1))
	if len1 > 0 {
		return true
	} else {
		return false
	}
	return false
}

//语种判断
func langJudge(str string) (sign int) {
	str = removePunctuation(str)
	//判断汉字
	reg := regexp.MustCompile(`[\P{Han}]+`)
	//fmt.Printf("%q\n", reg.FindAllString(str, -1))
	list1 := reg.FindAllString(str, -1)
	list1 = removeNUllStr(list1)
	list1 = removeNumStr(list1)
	//for _, v := range list1 {
	//	fmt.Println(v)
	//}
	len1 := len(list1)
	if len1 == 0 {
		return 0
	}
	//判断英文
	// 查找连续的非单词字母、非空白字符
	reg = regexp.MustCompile(`[^\w\s]+`)
	//fmt.Printf("%q\n", reg.FindAllString(str, -1))
	list2 := reg.FindAllString(str, -1)
	list2 = removeNUllStr(list2)
	list2 = removeNumStr(list2)
	len1 = len(list2)
	if len1 == 0 {
		return 1
	}
	countH := countHan(str)
	countE := countEng(str)
	if countH == countE && countE == 0 {
		return 2
	}
	if countH >= countE {
		countJ := sumJan(str)
		if float32(countJ)/float32(len(str)) > japanProportion {
			return 2
		} else {
			return 0
		}
	} else {
		return 1
	}
	return 2
}

//判别标识
var match []string = []string{"。", "？", "！", ".", "?", "!", ";", "；"}
var match1 []string = []string{",", "，"}

func split(s rune) bool {
	if judge(string(s)) {
		return true
	}
	return false
}
func judge(s string) bool {
	for _, v := range match {
		if v == s {
			return true
		}
	}
	return false
}
func split1(s rune) bool {
	if judge1(string(s)) {
		return true
	}
	return false
}
func judge1(s string) bool {
	for _, v := range match1 {
		if v == s {
			return true
		}
	}
	return false
}

//去除标点
func removePunctuation(str string) string {
	// 查找连续的单词字母
	reg1 := regexp.MustCompile(`[\w]+`)
	//fmt.Printf("%q\n", reg1.FindAllString(str, -1))
	// ["Hello" "123" "Go"]
	sign1 := len(reg1.FindAllString(str, -1))
	// 查找连续的非标点符号字符
	reg := regexp.MustCompile(`[\PP]+`)
	//fmt.Printf("%q\n", reg.FindAllString(str, -1))
	list := reg.FindAllString(str, -1)
	var strIn string = ""
	for _, val := range list {
		if sign1 == 0 {
			//全汉字可能的时候直接连接
			strIn = strIn + val
			strIn = removeBlankSpace(strIn)
		} else {
			if len(reg1.FindAllString(val, -1)) > 0 {
				//如果为单词
				strIn = strIn + " " + val
			} else {
				strIn = strIn + val
			}
		}
	}
	return strIn
}

//移除数字
func removeNumStr(strs []string) (newStrs []string) {
	reg := `[\D]+`
	reg1 := regexp.MustCompile(reg)
	for _, v := range strs {
		v = removeBlankSpace(v)
		if reg1.MatchString(v) {
			newStrs = append(newStrs, v)
		}
	}
	return
}

//移除数字
func removeNUMStr(strs []string) (newStrs []string) {
	//reg := `[\PP]+`
	//reg1 := regexp.MustCompile(reg)
	//for _, v := range strs {
	//	if reg1.MatchString(v) {
	//		newStrs = append(newStrs, v)
	//	}
	//}
	reg1 := regexp.MustCompile(`[\f\t\n\r\v\123\x7F\x{10FFFF}\\\^\$\.\*\+\?\{\}\(\)\[\]\|]`)
	//reg1 = regexp.MustCompile(`[^[:name:]]`)
	for _, v := range strs {
		if !reg1.MatchString(v) {
			newStrs = append(newStrs, v)
		}
	}
	return
}

//移除空串
func removeNUllStr(strs []string) (newStrs []string) {
	reg := `[\S]+`
	reg1 := regexp.MustCompile(reg)
	for _, v := range strs {
		if reg1.MatchString(v) {
			newStrs = append(newStrs, v)
		}
	}
	return
}

//移除空格
func removeBlankSpace(str string) string {
	reg := `[\S]+`
	return regRemove(str, reg)
}

//基本移除
func regRemove(str string, reg string) string {
	reg1 := regexp.MustCompile(reg)
	//fmt.Printf("%q\n", reg1.FindAllString(str, -1))
	list := reg1.FindAllString(str, -1)
	var strIn string = ""
	for _, val := range list {
		strIn = strIn + val
	}
	return strIn
}

//分词
func sliceWord(str string, segmenter sego.Segmenter) (output []string) {
	text := []byte(str)
	segments := segmenter.Segment(text)
	output = sego.SegmentsToSlice(segments, false)
	return
}

//统计汉字字符总长
func countHan(str string) (num int) {
	reg := regexp.MustCompile(`[\p{Han}]+`)
	//fmt.Printf("%q\n", reg.FindAllString(str, -1))
	list1 := reg.FindAllString(str, -1)
	num = 0
	for _, v := range list1 {
		num = num + len(v)
	}
	return
}

//统计英文字符总长
func countEng(str string) (num int) {
	reg := regexp.MustCompile(`[\w]+`)
	//fmt.Printf("%q\n", reg.FindAllString(str, -1))
	list2 := reg.FindAllString(str, -1)
	list2 = removeNumStr(list2)
	num = 0
	for _, v := range list2 {
		num = num + len(v)
	}
	return
}

//过滤函数
func filterFun(str string) (sig bool) {
	reg := regexp.MustCompile(`[\PP]+`)
	leng := reg.FindAllString(str, -1)
	leng = removeNUllStr(leng)
	leng = removeNUMStr(leng)
	if len(leng) == 0 {
		return false
	}
	reg = regexp.MustCompile(`[^\s]+`)
	leng = reg.FindAllString(str, -1)
	if len(leng) == 0 {
		return false
	}

	return true
}

//统计假名字符量`[\p{Han}]+`
func sumJan(str string) (count int) {
	reg := `[\p{Hiragana}]+`
	str1 := regRemove(str, reg)
	reg = `[\p{Katakana}]+`
	str2 := regRemove(str, reg)
	count = len(str1) + len(str2)
	return
}
